package com.heu.blood.storge.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heu.blood.common.Constant.ConstantData;
import com.heu.blood.common.aop.ServiceLogAnnotation;
import com.heu.blood.common.commponent.DictBloodProductLoader;
import com.heu.blood.common.commponent.DictionaryLoader;
import com.heu.blood.common.enums.BloodStateEnum;
import com.heu.blood.common.utils.ExcelUtil;
import com.heu.blood.common.utils.GenerateNumberBySnowFlake;
import com.heu.blood.common.utils.PageUtils;
import com.heu.blood.common.utils.Query;
import com.heu.blood.dict.dao.DictBloodProductDao;
import com.heu.blood.dict.entity.DictBloodProductEntity;
import com.heu.blood.globalExceptionHandler.MyException;
import com.heu.blood.match.dao.BloodInformationDao;
import com.heu.blood.match.entity.BloodInformationEntity;
import com.heu.blood.match.service.BloodInformationService;
import com.heu.blood.recycle.dao.BloodReturnDao;
import com.heu.blood.recycle.dictenum.BloodReturnReasonEnum;
import com.heu.blood.recycle.dictenum.BloodReturnVerifyStateEnum;
import com.heu.blood.recycle.entity.BloodReturnEntity;
import com.heu.blood.security.entity.LoginUser;
import com.heu.blood.storge.dao.BloodInStorgeDao;
import com.heu.blood.storge.entity.BloodInStorgeEntity;
import com.heu.blood.storge.exception.InstorageException;
import com.heu.blood.storge.listener.ImportDataListener;
import com.heu.blood.storge.service.BloodInStorgeService;
import com.heu.blood.storge.service.BloodVerifyStorgeService;
import com.heu.blood.storge.vo.BloodDeleteReturnVo;
import com.heu.blood.storge.vo.BloodInformationAndInStorageVo;
import com.heu.blood.storge.vo.BloodInformationForExcelVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.heu.blood.common.enums.BloodStorgeEnum.*;
import static com.heu.blood.common.enums.CommonEnum.*;

@Slf4j
@Service("bloodInStorgeService")
public class BloodInStorgeServiceImpl extends ServiceImpl<BloodInStorgeDao, BloodInStorgeEntity> implements BloodInStorgeService {


    @Autowired
    private BloodInStorgeDao bloodInStorgeDao;
    @Autowired
    private BloodInformationService bloodInformationService;
    @Autowired
    private BloodInformationDao bloodInformationDao;
    @Autowired
    private DictionaryLoader dictionaryLoader;
    @Autowired
    private ImportDataListener importDataListener;
    @Lazy
    @Autowired
    private BloodVerifyStorgeService verifyStorgeService;
    @Autowired
    private DictBloodProductLoader dictBloodProductLoader;

    @Autowired
    private DictBloodProductDao dictBloodProductDao;

    @Autowired
    private BloodReturnDao bloodReturnDao;

    //分页查询部分
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        //构造bloodInStorge
        BloodInStorgeEntity bloodInStorgeEntity = new BloodInStorgeEntity();
        //用于接收传递过来的BloodInstorgeEntity参数
        log.info(String.valueOf(params));
        log.info(String.valueOf(params.get("batchNumber")));
        if(Strings.isNotBlank((String) params.get("bloodId"))){
            bloodInStorgeEntity.setBloodId((String) params.get("bloodId"));//添加bloodId
        }
        if (Strings.isNotBlank((String) params.get("extendCode"))){
            bloodInStorgeEntity.setExtendCode((String) params.get("extendCode")); // 添加产品码
        }
        if (Strings.isNotBlank((String) params.get("aboBloodType"))){
            bloodInStorgeEntity.setAboBloodType((String) params.get("aboBloodType")); // 添加aboBloodType
        }
        if (Strings.isNotBlank((String) params.get("rhBloodType"))){
            bloodInStorgeEntity.setRhBloodType((String) params.get("rhBloodType")); // 添加rhBloodType
            log.info(bloodInStorgeEntity.getRhBloodType());
        }
        if (Strings.isNotBlank((String) params.get("bloodType"))){
            bloodInStorgeEntity.setBloodType((String) params.get("bloodType")); // 添加bloodType
        }
        if (Strings.isNotBlank((String) params.get("bloodBankDeliveryId"))){
            bloodInStorgeEntity.setBloodBankDeliveryId((String) params.get("bloodBankDeliveryId")); // 添加bloodBankDeliveryId 出库编号
        }
        if (Strings.isNotBlank((String) params.get("bloodSource"))){
            bloodInStorgeEntity.setBloodSource((String) params.get("bloodSource")); // 添加bloodSource供血机构
        }
        if (Strings.isNotBlank((String) params.get("operatorName"))){
            bloodInStorgeEntity.setOperatorName((String) params.get("operatorName")); // 添加operatorName入库者姓名
        }
        if (Strings.isNotBlank((String) params.get("number"))){
            bloodInStorgeEntity.setNumber((String) params.get("number")); // 添加number入库单据号
        }
        if (Strings.isNotBlank(String.valueOf(params.get("batchNumber")))){
            log.info("-------------------");
            if(!String.valueOf(params.get("batchNumber")).equals(new String("null"))){
                bloodInStorgeEntity.setBatchNumber(Long.valueOf(String.valueOf(params.get("batchNumber")))); // 添加batchNumber入库批次号
            }
            log.info(String.valueOf(bloodInStorgeEntity.getBatchNumber()));
            log.info("-----------------------------");
        }
        if (Strings.isNotBlank(String.valueOf(params.get("bloodState")))){
            bloodInStorgeEntity.setBloodState((String)params.get("bloodState"));
        }
        // 时间格式化，解决Date->String 报错
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //前端应该传来一个入库开始日期一个入库结束日期
        String inStorgeTimeStart = (String)params.get("startTime");
        String inStorgeTimeEnd = (String) params.get("endTime");
        Date start = null;//声明两个date 开始和结束
        Date end = null;
        if(Strings.isNotBlank(inStorgeTimeStart) && inStorgeTimeStart!="null"){
            try {
                start = sdf.parse(inStorgeTimeStart);
                log.info("-----------------------------");
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        if(Strings.isNotBlank(inStorgeTimeEnd) && inStorgeTimeEnd!="null"){
            try {
                end = sdf.parse(inStorgeTimeEnd);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        // 构造条件构造器对象
        LambdaQueryWrapper<BloodInStorgeEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 添加过滤条件
        queryWrapper.like(Strings.isNotBlank(bloodInStorgeEntity.getBloodId()),BloodInStorgeEntity::getBloodId,bloodInStorgeEntity.getBloodId())
                .eq(Strings.isNotBlank(bloodInStorgeEntity.getExtendCode()), BloodInStorgeEntity::getExtendCode, bloodInStorgeEntity.getExtendCode())
                .eq(Strings.isNotBlank(bloodInStorgeEntity.getAboBloodType()), BloodInStorgeEntity::getAboBloodType, bloodInStorgeEntity.getAboBloodType())
                .eq(Strings.isNotBlank(bloodInStorgeEntity.getRhBloodType()), BloodInStorgeEntity::getRhBloodType, bloodInStorgeEntity.getRhBloodType())
                .eq(Strings.isNotBlank(bloodInStorgeEntity.getBloodType()), BloodInStorgeEntity::getBloodType, bloodInStorgeEntity.getBloodType())
                .eq(Strings.isNotBlank(bloodInStorgeEntity.getBloodBankDeliveryId()), BloodInStorgeEntity::getBloodBankDeliveryId, bloodInStorgeEntity.getBloodBankDeliveryId())
                .eq(Strings.isNotBlank(bloodInStorgeEntity.getBloodSource()), BloodInStorgeEntity::getBloodSource, bloodInStorgeEntity.getBloodSource())
                .eq(Strings.isNotBlank(bloodInStorgeEntity.getOperatorName()), BloodInStorgeEntity::getOperatorName, bloodInStorgeEntity.getOperatorName())
                .eq(Strings.isNotBlank(bloodInStorgeEntity.getNumber()), BloodInStorgeEntity::getNumber, bloodInStorgeEntity.getNumber())
                .eq(Strings.isNotBlank(String.valueOf(bloodInStorgeEntity.getBatchNumber()))&&String.valueOf(bloodInStorgeEntity.getBatchNumber())!="null", BloodInStorgeEntity::getBatchNumber, bloodInStorgeEntity.getBatchNumber())
                .eq(Strings.isNotBlank(bloodInStorgeEntity.getBloodState()),BloodInStorgeEntity::getBloodState,bloodInStorgeEntity.getBloodState())
                .eq(BloodInStorgeEntity::getIsDeleted,IS_NOT_DELETED.code())
                .eq(BloodInStorgeEntity::getIfShow,IF_SHOW.code())
                .ge(start != null, BloodInStorgeEntity::getInStorgeTime, start)
                .le(end != null, BloodInStorgeEntity::getInStorgeTime, end);

        queryWrapper.orderByDesc(BloodInStorgeEntity::getInStorgeTime);
        IPage<BloodInStorgeEntity> page = this.page(
                new Query<BloodInStorgeEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }
    @Transactional
    @Override
    public int insertInStorge(BloodInStorgeEntity bloodInStorgeEntity) {
        // 先确认一下有没有重复的血液id
        LambdaQueryWrapper<BloodInStorgeEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BloodInStorgeEntity::getBloodId,bloodInStorgeEntity.getBloodId());
        BloodInStorgeEntity verifyEntity = bloodInStorgeDao.selectOne(queryWrapper);
        if(verifyEntity != null){
            throw new MyException(InstorageException.DUPLICATE_BLOODID);
        }
        bloodInStorgeEntity.setBloodState(BloodStateEnum.IN_STORAGE_TEST.code());//初始化血液状态
        bloodInStorgeEntity.setInStorgeTime(new Date());//设置入库日期
        //入库表插入一条数据
        int flag;
        flag = bloodInStorgeDao.insert(bloodInStorgeEntity);
        log.info(String.valueOf(new Date()));
        log.info("========================================");
        return flag;
    }

    @Override
    public boolean updateInStorgeBloodStatebyBloodId(String BloodId, String state) {
        //调用updatewrapper 进行血液状态更新
        LambdaUpdateWrapper<BloodInStorgeEntity> updateWapper = new LambdaUpdateWrapper<>();
        updateWapper.eq(Strings.isNotBlank(BloodId),BloodInStorgeEntity::getBloodId,BloodId);
        updateWapper.set(BloodInStorgeEntity::getBloodState,state);
        //记录结果
        int res = bloodInStorgeDao.update(null,updateWapper);
        //判断状态是否是否成功

        return res==1;
    }

    @Override
    public boolean updateBloodInformationByBloodId(BloodInStorgeEntity bloodInStorgeEntity) {
        //调用updatewrapper进行bloodinformation 表的更新
        LambdaUpdateWrapper<BloodInformationEntity> updateWrapper = new LambdaUpdateWrapper<>();
        //根据id寻找到bloodinformation对象
        updateWrapper.eq(Strings.isNotBlank(bloodInStorgeEntity.getBloodId()),BloodInformationEntity::getBloodId,bloodInStorgeEntity.getBloodId())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getBloodType()),BloodInformationEntity::getBloodType,bloodInStorgeEntity.getBloodType())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getAboBloodType()),BloodInformationEntity::getAboBloodType,bloodInStorgeEntity.getAboBloodType())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getRhBloodType()),BloodInformationEntity::getRhBloodType,bloodInStorgeEntity.getRhBloodType())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getBloodDonationCode()),BloodInformationEntity::getBloodDonationCode,bloodInStorgeEntity.getBloodDonationCode())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getExtendCode()),BloodInformationEntity::getExtendCode,bloodInStorgeEntity.getExtendCode())
                .set(Strings.isNotBlank(String.valueOf(bloodInStorgeEntity.getBloodCount())),BloodInformationEntity::getBloodCount,bloodInStorgeEntity.getBloodCount())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getMeasurementUnit()),BloodInformationEntity::getMeasurementUnit,bloodInStorgeEntity.getMeasurementUnit())
                .set(Strings.isNotBlank(String.valueOf(bloodInStorgeEntity.getBatchNumber())),BloodInformationEntity::getBatchNumber,bloodInStorgeEntity.getBatchNumber())
                .set(Strings.isNotBlank(String.valueOf(bloodInStorgeEntity.getCollectTime())),BloodInformationEntity::getCollectTime,bloodInStorgeEntity.getCollectTime())
                .set(Strings.isNotBlank(String.valueOf(bloodInStorgeEntity.getFailureTime())),BloodInformationEntity::getFailureTime,bloodInStorgeEntity.getFailureTime())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getHospitalClassification()),BloodInformationEntity::getHospitalClassification,bloodInStorgeEntity.getHospitalClassification())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getBloodSource()),BloodInformationEntity::getBloodSource,bloodInStorgeEntity.getBloodSource())
                .set(Strings.isNotBlank(String.valueOf(bloodInStorgeEntity.getBloodPrice())),BloodInformationEntity::getBloodPrice,bloodInStorgeEntity.getBloodPrice())
                .set(Strings.isNotBlank(String.valueOf(bloodInStorgeEntity.getInboundPrice())),BloodInformationEntity::getInboundPrice,bloodInStorgeEntity.getInboundPrice())
                .set(Strings.isNotBlank(String.valueOf(bloodInStorgeEntity.getBarcode())),BloodInformationEntity::getBarcode,bloodInStorgeEntity.getBarcode())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getBloodLocation()),BloodInformationEntity::getBloodLocation,bloodInStorgeEntity.getBloodLocation())
                .set(Strings.isNotBlank(bloodInStorgeEntity.getBloodState()),BloodInformationEntity::getBloodState,bloodInStorgeEntity.getBloodState());
        int res = bloodInformationDao.update(null,updateWrapper);
        return res==1;
    }

    @Transactional
    @Override
    public boolean  batchInsertWithVerify(List<BloodInStorgeEntity> bloodInStorgeEntityList) {

        // 这里需要先去查询所有已存在的id
        List<String> bloodIdList = new ArrayList<>();
        for(BloodInStorgeEntity curVo : bloodInStorgeEntityList){
            if(Strings.isBlank(curVo.getBloodId())){
                throw new MyException(InstorageException.NO_BLOODID);
            }else{
                bloodIdList.add(curVo.getBloodId());
            }
        }
        LambdaQueryWrapper<BloodInStorgeEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BloodInStorgeEntity::getBloodId,bloodIdList);
        List<BloodInStorgeEntity> inStorageList = this.list(queryWrapper);
        if(inStorageList.size() != 0){
            throw new MyException(InstorageException.DUPLICATE_BLOODID);
        }

        // 获取可以翻译中文到code的字典
        Map<String, String> bloodTypeDictTranslate = dictionaryLoader.getBloodTypeDictTranslate();
        Map<String, String> measurementUnitDictTranslate = dictionaryLoader.getMeasurementUnitDictTranslate();
        for(BloodInStorgeEntity bloodInStorgeEntity : bloodInStorgeEntityList){
            bloodInStorgeEntity.setBloodState(INSERT_STORGE_SUCCESS.code());//初始化血液状态
            bloodInStorgeEntity.setInStorgeTime(new Date());//设置入库日期
            GenerateNumberBySnowFlake generateNumberBySnowFlake = new GenerateNumberBySnowFlake(bloodInStorgeEntity.getOperatorName() ,"RK");
            bloodInStorgeEntity.setNumber(generateNumberBySnowFlake.genNumberByflag()); //设置入库单据号
            // 根据中文翻译成code
            String bloodTypeCode = bloodTypeDictTranslate.get(bloodInStorgeEntity.getBloodType());
            String measurementUnitCode = measurementUnitDictTranslate.get(bloodInStorgeEntity.getMeasurementUnit());
            // 把code设置进去
            bloodInStorgeEntity.setBloodType(bloodTypeCode);
            bloodInStorgeEntity.setMeasurementUnit(measurementUnitCode);
        }
        log.info("----------------------------------");
        //批量插入
        boolean res1 = this.saveBatch(bloodInStorgeEntityList);//记录批量入库是否操作成功
        //改为不同时向bloodinformation批量插入
        //boolean res2 = bloodInformationService.saveBatch(bloodInformationEntityList);
        return res1;
    }

    @Override
    public List<Map> getListByExcel(InputStream is, String fileName) {
        try{
            //解析Excel中的数据
            List<Map> BloodInformationList = new ExcelUtil(new BloodInformationForExcelVo()).AnalysisExcel(is, fileName);
           //每个Map对应一个Entity实体的map解析
//            for(Map map : BloodInformationList){
//                //对于每个map应该提供一个封装成实体类的接口
//            }
            return BloodInformationList;
        }catch (Exception e){
            e.printStackTrace();
        }
        return new ArrayList<>();

    }

    @Transactional
    @Override
    public Boolean batchImportBloodInformationInfo(List<Map> bloodInformationList) {
        //存储血液库存信息的
        List<BloodInformationEntity> bloodInformationEntityList = new ArrayList<>();
        //存储入库信息列表
        List<BloodInStorgeEntity> bloodInStorgeEntityList = new ArrayList<>();
        for (Map map : bloodInformationList) {
            //装载列表
            bloodInformationEntityList.add(bloodInformationService.convertFromMapToEntity(map));
            bloodInStorgeEntityList.add(converMaptoInStorgeEntity(map));
        }
        //记录是否插入成功
        boolean res1  = this.saveBatch(bloodInStorgeEntityList);
        boolean res2  = bloodInformationService.saveBatch(bloodInformationEntityList);
        return res1 && res2;
    }

    @Override
    public BloodInStorgeEntity converMaptoInStorgeEntity(Map bloodInformationMap) {
        Map<String,String> subDict = dictionaryLoader.getSubDict();
        BloodInStorgeEntity bloodInStorgeEntity = new BloodInStorgeEntity();
        if (bloodInformationMap.size() != 0){//解析成功
                if(bloodInformationMap.get("bloodId") != null)
                    bloodInStorgeEntity.setBloodId((String) bloodInformationMap.get("bloodId"));
                if(bloodInformationMap.get("extendCode") != null)
                    bloodInStorgeEntity.setExtendCode((String) bloodInformationMap.get("extendCode"));
                if(bloodInformationMap.get("bloodType") != null){
                    String newBloodType = subDict.get((String) bloodInformationMap.get("bloodType"));
                    bloodInStorgeEntity.setBloodType(newBloodType);
                }
                if(bloodInformationMap.get("bloodCount") != null)
                    bloodInStorgeEntity.setBloodCount(new BigDecimal(String.valueOf(bloodInformationMap.get("bloodCount"))));
                if(bloodInformationMap.get("aboBloodType") != null){
                    String newAboBloodType = subDict.get((String) bloodInformationMap.get("aboBloodType"));
                    bloodInStorgeEntity.setAboBloodType(newAboBloodType);
                }
                if(bloodInformationMap.get("rhBloodType") != null){
                    String newRhBloodType = subDict.get((String)bloodInformationMap.get("rhBloodType"));
                    bloodInStorgeEntity.setRhBloodType(newRhBloodType);
                }
                //时间格式已经转换成yyyy-MM-dd
                if(bloodInformationMap.get("failureTime") != null)
                    bloodInStorgeEntity.setFailureTime(java.sql.Date.valueOf(String.valueOf(bloodInformationMap.get("failureTime"))));
                if(bloodInformationMap.get("collectTime") != null)
                    bloodInStorgeEntity.setCollectTime(java.sql.Date.valueOf(String.valueOf(bloodInformationMap.get("collectTime"))));
                if(bloodInformationMap.get("bloodSource") != null){
                    String newBloodSource = subDict.get((String) bloodInformationMap.get("bloodSource"));
                    bloodInStorgeEntity.setBloodSource(newBloodSource);
                }
                if(bloodInformationMap.get("measurementUnit") != null){
                    String newMeasurementUnit = subDict.get((String) bloodInformationMap.get("measurementUnit"));
                    bloodInStorgeEntity.setMeasurementUnit(newMeasurementUnit);
                }
                if(bloodInformationMap.get("batchNumber") != null) {
                    if (String.valueOf(bloodInformationMap.get("batchNumber")).equals(new String("null"))) {
                        bloodInStorgeEntity.setBatchNumber(null);
                    } else {
                        double doubleValue = Double.parseDouble(String.valueOf(bloodInformationMap.get("batchNumber")));
                        long longValue = (long) doubleValue;
                        bloodInStorgeEntity.setBatchNumber(longValue);
                    }
                }
                if(bloodInformationMap.get("bloodPrice") != null)
                    bloodInStorgeEntity.setBloodPrice((BigDecimal) bloodInformationMap.get("bloodPrice"));
                if(bloodInformationMap.get("inboundPrice") != null)
                    bloodInStorgeEntity.setInboundPrice((BigDecimal) bloodInformationMap.get("inboundPrice"));
                if(bloodInformationMap.get("bloodLocation")!=null)
                    bloodInStorgeEntity.setBloodLocation((String) bloodInformationMap.get("bloodLocation"));
                if(bloodInformationMap.get("barcode") != null)
                    bloodInStorgeEntity.setBarcode( (String)bloodInformationMap.get("barcode"));

                if(bloodInformationMap.get("bloodDonationCode") != null)
                    bloodInStorgeEntity.setBloodDonationCode((String) bloodInformationMap.get("bloodDonationCode"));
                if(bloodInformationMap.get("bloodBankDeliveryId") != null)
                    bloodInStorgeEntity.setBloodBankDeliveryId((String) bloodInformationMap.get("bloodBankDeliveryId"));
                if(bloodInformationMap.get("hospitalClassification") != null){
                    String newhospitalClassification = subDict.get((String) bloodInformationMap.get("hospitalClassification"));
                    bloodInStorgeEntity.setHospitalClassification(newhospitalClassification);
                }
                bloodInStorgeEntity.setBloodState(INSERT_STORGE_SUCCESS.code());//初始化血液状态
                bloodInStorgeEntity.setInStorgeTime(new Date());//设置入库日期
                //获取当前线程认证信息
                Authentication authentication= SecurityContextHolder.getContext().getAuthentication();
                if(authentication != null && authentication.isAuthenticated()){
                //获取当前用户id、name
                LoginUser loginUser = (LoginUser) authentication.getPrincipal();
                //写入当前用户信息
                //操作人姓名
                bloodInStorgeEntity.setOperatorName(loginUser.getUser().getUserName());
                //操作人工号
                bloodInStorgeEntity.setOperatorId(loginUser.getUser().getUserId());
                //入库使用雪花算法
                GenerateNumberBySnowFlake generateNumberBySnowFlake = new GenerateNumberBySnowFlake(bloodInStorgeEntity.getOperatorId(), STORGE_DOCUMENT_NUMBER.code());
                //生成单据号
                bloodInStorgeEntity.setNumber(generateNumberBySnowFlake.genNumberByflag()); //设置入库单据号
            }

        }
        return bloodInStorgeEntity;
    }

    @Override
    public Integer inStorgeNum() {
        LocalDate curDate = LocalDate.now();
        //获取当天的时间
        LocalDateTime startOfDay = LocalDateTime.of(curDate, LocalTime.MIN);
        LocalDateTime endOfDay = LocalDateTime.of(curDate,LocalTime.MAX);
        //创建lambdaquerywapper
        LambdaQueryWrapper<BloodInStorgeEntity> querywrapper = new LambdaQueryWrapper<>();
        //添加查询条件，使用日期范围查询
        querywrapper.between(BloodInStorgeEntity::getInStorgeTime, startOfDay, endOfDay)
                .eq(BloodInStorgeEntity::getIfShow,IF_SHOW.code())
                .eq(BloodInStorgeEntity::getIsDeleted,IS_NOT_DELETED.code())
                .eq(BloodInStorgeEntity::getBloodState,BLOOD_IN_STOCK_STATE.code());
        return bloodInStorgeDao.selectCount(querywrapper);
    }

    @Override
    public void importExcel(MultipartFile multipartFile) {
        InputStream inputStream = null;
        try {
            inputStream = multipartFile.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(inputStream, BloodInformationEntity.class,importDataListener).sheet().doRead();
    }

    //更新在库状态
    @Override
    public void BatchUpdateBloodStateInStockForInstorge(String[] bloodids) {
        List<String> bloodidslist = Arrays.asList(bloodids);
        bloodInStorgeDao.BatchUpdateBloodStateForInstorge(bloodidslist,BLOOD_IN_STOCK_STATE.code());
    }
    //更新退血状态
    @Override
    public void BatchUpdateBloodReturnStateForInstorge(String[] bloodids) {
        List<String> bloodidslist = Arrays.asList(bloodids);
        bloodInStorgeDao.BatchUpdateBloodStateForInstorge(bloodidslist,BLOOD_RETURN_TO_STATION.code());
    }

    @Transactional
    @Override
    public void insertOneInformationToBloodInformationFromBloodInStorgeByBloodId(String bloodId) {
        LambdaQueryWrapper<BloodInStorgeEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Strings.isNotBlank(bloodId),BloodInStorgeEntity::getBloodId,bloodId)
          .eq(BloodInStorgeEntity::getIfShow,IF_SHOW.code())
          .eq(BloodInStorgeEntity::getIsDeleted,IS_NOT_DELETED.code());
        BloodInStorgeEntity bloodInStorgeEntity = bloodInStorgeDao.selectOne(queryWrapper);
        BloodInformationEntity bloodInformationEntity = this.convertBloodInStorgeToBloodInformation(bloodInStorgeEntity);
        Map<String, String> dictCodeMap = dictBloodProductLoader.getchildToParent();
        String bloodType = bloodInformationEntity.getBloodType();
        LambdaQueryWrapper<DictBloodProductEntity> bloodProductQuery = new LambdaQueryWrapper<>();
        bloodProductQuery.eq(Strings.isNotBlank(bloodType), DictBloodProductEntity::getDictCode, bloodType);
        DictBloodProductEntity dictBloodProduct = dictBloodProductDao.selectOne(bloodProductQuery);
        bloodInformationEntity.setBloodTypeCode(dictBloodProduct.getCode());
        bloodInformationEntity.setComponentCategory(dictCodeMap.get(bloodType));
        bloodInformationService.save(bloodInformationEntity);
        this.updateInStorgeBloodStatebyBloodId(bloodInStorgeEntity.getBloodId(),BloodStateEnum.IN_STOCK.code());

    }
    @Override
    public BloodInformationEntity convertBloodInStorgeToBloodInformation(BloodInStorgeEntity bloodInStorgeEntity) {
        //创建一个新的血液信息对象
        BloodInformationEntity bloodInformationEntity = new BloodInformationEntity();
        //bloodInformationEntity.setBloodId();
        bloodInformationEntity.setBloodId(bloodInStorgeEntity.getBloodId());
        bloodInformationEntity.setBloodPrice(bloodInStorgeEntity.getBloodPrice());
        bloodInformationEntity.setBloodLocation(bloodInStorgeEntity.getBloodLocation());
        bloodInformationEntity.setBloodSource(bloodInStorgeEntity.getBloodSource());
        bloodInformationEntity.setBloodType(bloodInStorgeEntity.getBloodType());
        bloodInformationEntity.setRhBloodType(bloodInStorgeEntity.getRhBloodType());
        bloodInformationEntity.setBarcode(bloodInStorgeEntity.getBarcode());
        bloodInformationEntity.setBloodCount(bloodInStorgeEntity.getBloodCount());
        bloodInformationEntity.setAboBloodType(bloodInStorgeEntity.getAboBloodType());
        bloodInformationEntity.setRhBloodType(bloodInStorgeEntity.getRhBloodType());
        bloodInformationEntity.setFailureTime(bloodInStorgeEntity.getFailureTime());
        bloodInformationEntity.setCollectTime(bloodInStorgeEntity.getCollectTime());
        bloodInformationEntity.setBloodSource(bloodInStorgeEntity.getBloodSource());
        bloodInformationEntity.setInboundPrice(bloodInStorgeEntity.getInboundPrice());
        bloodInformationEntity.setBloodLocation(bloodInStorgeEntity.getBloodLocation());
        bloodInformationEntity.setMeasurementUnit(bloodInStorgeEntity.getMeasurementUnit());
        bloodInformationEntity.setBatchNumber(bloodInStorgeEntity.getBatchNumber());
        bloodInformationEntity.setBloodDonationCode(bloodInStorgeEntity.getBloodDonationCode());
        bloodInformationEntity.setBloodBankDeliveryId(bloodInStorgeEntity.getBloodBankDeliveryId());
        bloodInformationEntity.setHospitalClassification(bloodInStorgeEntity.getHospitalClassification());
        bloodInformationEntity.setBloodState(BloodStateEnum.IN_STOCK.code());
        bloodInformationEntity.setTestFlag(Integer.valueOf(IS_TEST_FLAG.code()));
        return bloodInformationEntity;
    }

    @Transactional
    @Override
    public void InsertMultiplyInformationToBloodInformationFromBloodInStorgeByBLoodId(String[] bloodIds) {
        LambdaQueryWrapper<BloodInStorgeEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BloodInStorgeEntity::getBloodId,bloodIds)
                    .eq(BloodInStorgeEntity::getIfShow,IF_SHOW.code())
                    .eq(BloodInStorgeEntity::getIsDeleted,IS_NOT_DELETED.code());
        List<BloodInStorgeEntity> bloodInStorgeEntityList = this.getBaseMapper().selectList(queryWrapper);
        Set<String> bloodTypes = bloodInStorgeEntityList.stream()
                .map(BloodInStorgeEntity::getBloodType)
                .filter(Strings::isNotBlank)
                .collect(Collectors.toSet());
        Map<String, String> dictCodeMap = dictBloodProductLoader.getchildToParent();
        LambdaQueryWrapper<DictBloodProductEntity> dictQuery = new LambdaQueryWrapper<>();
        dictQuery.in(DictBloodProductEntity::getDictCode, bloodTypes);
        List<DictBloodProductEntity> dictList = dictBloodProductDao.selectList(dictQuery);
        Map<String, DictBloodProductEntity> dictMap = dictList.stream()
                .collect(Collectors.toMap(DictBloodProductEntity::getDictCode, e -> e));
        List<BloodInformationEntity> bloodInformationEntityList = new ArrayList<>();
        for (BloodInStorgeEntity bloodInStorgeEntity : bloodInStorgeEntityList) {
            //将入库对象转变为血液信息对象
            BloodInformationEntity bloodInformationEntity = this.convertBloodInStorgeToBloodInformation(bloodInStorgeEntity);
            String bloodType = bloodInformationEntity.getBloodType();
            DictBloodProductEntity dictBloodProduct = dictMap.get(bloodType);
            bloodInformationEntity.setBloodTypeCode(dictBloodProduct.getCode());
            bloodInformationEntity.setComponentCategory(dictCodeMap.get(bloodType));
            bloodInformationEntityList.add(bloodInformationEntity);
        }
        bloodInformationService.saveBatch(bloodInformationEntityList);
        this.BatchUpdateBloodStateInStockForInstorge(bloodIds);
       log.info("-------------------------");
       verifyStorgeService.batchUpdateVerifyResultForVerifyStorgeByBloodId(bloodIds);

    }

    /**
     * 避免检验，直接进行单条血液入库，并更新为血液在库状况
     * @param bloodInformationAndInStorageVo
     * @return
     */
    @Override
    @Transactional
    public int insertWithoutVerify(BloodInformationAndInStorageVo bloodInformationAndInStorageVo) {
        // 首先得先确认数据有没有成功导入进去
        LambdaQueryWrapper<BloodInStorgeEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BloodInStorgeEntity::getBloodId,bloodInformationAndInStorageVo.getBloodId());
        BloodInStorgeEntity verifyEntity = bloodInStorgeDao.selectOne(queryWrapper);
        if(verifyEntity != null){
            throw new MyException(InstorageException.DUPLICATE_BLOODID);
        }
        Map<String, String> dictCodeMap = dictBloodProductLoader.getchildToParent();
        bloodInformationAndInStorageVo.setBloodState(BloodStateEnum.IN_STOCK.code());//初始化血液状态
        bloodInformationAndInStorageVo.setInStorgeTime(new Date());//设置入库时间
        BloodInStorgeEntity bloodInStorgeEntity = new BloodInStorgeEntity();
        BloodInformationEntity bloodInformationEntity = new BloodInformationEntity();
        BeanUtils.copyProperties(bloodInformationAndInStorageVo,bloodInStorgeEntity);
        BeanUtils.copyProperties(bloodInformationAndInStorageVo,bloodInformationEntity);
        String bloodType = bloodInformationEntity.getBloodType();
        LambdaQueryWrapper<DictBloodProductEntity> bloodProductQuery = new LambdaQueryWrapper<>();
        bloodProductQuery.eq(Strings.isNotBlank(bloodType), DictBloodProductEntity::getDictCode, bloodType);
        DictBloodProductEntity dictBloodProduct = dictBloodProductDao.selectOne(bloodProductQuery);
        String code = dictBloodProduct.getCode();
        bloodInformationEntity.setBloodTypeCode(code);
        bloodInformationEntity.setComponentCategory(dictCodeMap.get(bloodType));

//        GenerateNumberBySnowFlake generateNumberBySnowFlake = new GenerateNumberBySnowFlake(ConstantData.BLOOD_CENTER_DELIVERT_NO_WORK_ID, ConstantData.BLOOD_CENTER_DELIVERT_NO_PREFIX);
//        String bloodCenterDeliveryId = generateNumberBySnowFlake.genNumberByflag();
//
//        GenerateNumberBySnowFlake generateNumberBySnowFlakeIn = new GenerateNumberBySnowFlake(ConstantData.BLOOD_IN_STORAGE_NO_WORK_ID ,ConstantData.BLOOD_IN_STORAGE_NO_PREFIX);
//        String inStorageId = generateNumberBySnowFlakeIn.genNumberByflag();
//

        String centerPrefix = ConstantData.BLOOD_CENTER_DELIVERT_NO_PREFIX;
        String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
        QueryWrapper<BloodInStorgeEntity> centerWrapper = new QueryWrapper<>();
        centerWrapper.likeRight("blood_center_delivery_id", centerPrefix + dateStr);
        centerWrapper.orderByDesc("blood_center_delivery_id");
        centerWrapper.last("limit 1");
        BloodInStorgeEntity maxCenterEntity = bloodInStorgeDao.selectOne(centerWrapper);

        int nextCenterSeq = 1;
        if (maxCenterEntity != null && maxCenterEntity.getBloodCenterDeliveryId() != null) {
            String maxNo = maxCenterEntity.getBloodCenterDeliveryId();
            if (maxNo.length() >= 12) {
                String seqStr = maxNo.substring(10, 14);
                nextCenterSeq = Integer.parseInt(seqStr) + 1;
            }
        }
        String centerSeqStr = String.format("%04d", nextCenterSeq);
        String bloodCenterDeliveryId = centerPrefix + dateStr + centerSeqStr;

        // 生成入库编号
        String inPrefix = ConstantData.BLOOD_IN_STORAGE_NO_PREFIX;
        QueryWrapper<BloodInStorgeEntity> inWrapper = new QueryWrapper<>();
        inWrapper.likeRight("number", inPrefix + dateStr);
        inWrapper.orderByDesc("number");
        inWrapper.last("limit 1");
        BloodInStorgeEntity maxInEntity = bloodInStorgeDao.selectOne(inWrapper);

        int nextInSeq = 1;
        if (maxInEntity != null && maxInEntity.getNumber() != null) {
            String maxNo = maxInEntity.getNumber();
            if (maxNo.length() >= 12) {
                String seqStr = maxNo.substring(10, 14);
                nextInSeq = Integer.parseInt(seqStr) + 1;
            }
        }
        String inSeqStr = String.format("%04d", nextInSeq);
        String inStorageId = inPrefix + dateStr + inSeqStr;


        bloodInStorgeEntity.setNumber(inStorageId); //设置入库单据号
        bloodInStorgeEntity.setBloodCenterDeliveryId(bloodCenterDeliveryId);
        bloodInformationEntity.setBloodCenterDeliveryId(bloodCenterDeliveryId);
        bloodInformationEntity.setNumber(inStorageId); //设置入库单据号

        int insertInStorageFlag = bloodInStorgeDao.insert(bloodInStorgeEntity);
        int insertBloodInformationFlag = bloodInformationDao.insert(bloodInformationEntity);
        if(insertInStorageFlag == 0 || insertBloodInformationFlag == 0){
            return 0;
        }
        return 1;
    }

    @Override
    @Transactional
    public int batchInsertWithoutVerify(List<BloodInformationAndInStorageVo> bloodInformationAndInStorageVos) {
        // 这里需要先去查询所有已存在的id
        List<String> bloodIdList = new ArrayList<>();
        for(BloodInformationAndInStorageVo curVo : bloodInformationAndInStorageVos){
            if(Strings.isBlank(curVo.getBloodId())){
                throw new MyException(InstorageException.NO_BLOODID);
            }else{
                bloodIdList.add(curVo.getBloodId());
            }
        }
        LambdaQueryWrapper<BloodInStorgeEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BloodInStorgeEntity::getBloodId,bloodIdList);
        List<BloodInStorgeEntity> inStorageList = this.list(queryWrapper);
        if(inStorageList.size() != 0){
            throw new MyException(InstorageException.DUPLICATE_BLOODID);
        }


        List<BloodInformationEntity> bloodInformationEntities = new ArrayList<>();
        List<BloodInStorgeEntity> bloodInStorgeEntities = new ArrayList<>();
        // 在这查找一下所有的中文翻译英文的字典
        Map<String, String> bloodTypeDictTranslate = dictionaryLoader.getBloodTypeDictTranslate();
        Map<String, String> measurementUnitDictTranslate = dictionaryLoader.getMeasurementUnitDictTranslate();
        Map<String, String> dictCodeMap = dictBloodProductLoader.getchildToParent();


        String centerPrefix = ConstantData.BLOOD_CENTER_DELIVERT_NO_PREFIX;
        String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
        QueryWrapper<BloodInStorgeEntity> centerWrapper = new QueryWrapper<>();
        centerWrapper.likeRight("blood_center_delivery_id", centerPrefix + dateStr);
        centerWrapper.orderByDesc("blood_center_delivery_id");
        centerWrapper.last("limit 1");
        BloodInStorgeEntity maxCenterEntity = bloodInStorgeDao.selectOne(centerWrapper);
        int nextCenterSeq = 1;
        if (maxCenterEntity != null && maxCenterEntity.getBloodCenterDeliveryId() != null) {
            String maxNo = maxCenterEntity.getBloodCenterDeliveryId();
            if (maxNo.length() >= 12) {
                String seqStr = maxNo.substring(10, 14);
                nextCenterSeq = Integer.parseInt(seqStr) + 1;
            }
        }

        String inPrefix = ConstantData.BLOOD_IN_STORAGE_NO_PREFIX;
        QueryWrapper<BloodInStorgeEntity> inWrapper = new QueryWrapper<>();
        inWrapper.likeRight("number", inPrefix + dateStr);
        inWrapper.orderByDesc("number");
        inWrapper.last("limit 1");
        BloodInStorgeEntity maxInEntity = bloodInStorgeDao.selectOne(inWrapper);
        int nextInSeq = 1;
        if (maxInEntity != null && maxInEntity.getNumber() != null) {
            String maxNo = maxInEntity.getNumber();
            if (maxNo.length() >= 12) {
                String seqStr = maxNo.substring(10, 14);
                nextInSeq = Integer.parseInt(seqStr) + 1;
            }
        }

        for(BloodInformationAndInStorageVo vo : bloodInformationAndInStorageVos){
            vo.setBloodState(BloodStateEnum.IN_STOCK.code());//初始化血液状态
            vo.setInStorgeTime(new Date());//设置入库时间
            BloodInformationEntity bloodInformationEntity = new BloodInformationEntity();
            BloodInStorgeEntity bloodInStorgeEntity = new BloodInStorgeEntity();
            BeanUtils.copyProperties(vo,bloodInformationEntity);
            BeanUtils.copyProperties(vo,bloodInStorgeEntity);
            String centerSeqStr = String.format("%04d", nextCenterSeq++);
            String bloodCenterDeliveryId = centerPrefix + dateStr + centerSeqStr;
            String inSeqStr = String.format("%04d", nextInSeq++);
            String inStorageId = inPrefix + dateStr + inSeqStr;
            // 翻译后了再塞进去
            String bloodTypeCode = bloodTypeDictTranslate.get(bloodInStorgeEntity.getBloodType());
            String measurementUnitCode = measurementUnitDictTranslate.get(bloodInStorgeEntity.getMeasurementUnit());
            bloodInStorgeEntity.setBloodType(bloodTypeCode);
            bloodInStorgeEntity.setBloodCenterDeliveryId(bloodCenterDeliveryId);
            //String inStorageId = generateNumberBySnowFlakeIn.genNumberByflag();
            bloodInStorgeEntity.setNumber(inStorageId); //设置入库单据号
            bloodInformationEntity.setNumber(inStorageId);
            bloodInformationEntity.setBloodType(bloodTypeCode);
            bloodInformationEntity.setBloodCenterDeliveryId(bloodCenterDeliveryId);
            LambdaQueryWrapper<DictBloodProductEntity> bloodProductQuery = new LambdaQueryWrapper<>();
            bloodProductQuery.eq(Strings.isNotBlank(bloodTypeCode), DictBloodProductEntity::getDictCode, bloodTypeCode);
            DictBloodProductEntity dictBloodProduct = dictBloodProductDao.selectOne(bloodProductQuery);
            String code = dictBloodProduct.getCode();
            bloodInformationEntity.setBloodTypeCode(code);
            bloodInformationEntity.setComponentCategory(dictCodeMap.get(bloodTypeCode));
            bloodInStorgeEntity.setMeasurementUnit(measurementUnitCode);
            bloodInformationEntity.setMeasurementUnit(measurementUnitCode);
            bloodInformationEntities.add(bloodInformationEntity);
            bloodInStorgeEntities.add(bloodInStorgeEntity);

        }
        boolean saveInstorageFlag = this.saveBatch(bloodInStorgeEntities);
        boolean saveInformationFlag = bloodInformationService.saveBatch(bloodInformationEntities);
        if(saveInformationFlag && saveInstorageFlag){
            return 1;
        }
        return 0;
    }

    @Override
    @ServiceLogAnnotation(module = "血液入库", operate = "回显血液入库信息")
    public BloodInStorgeEntity queryStorageByBloodId(String bloodId) {

        LambdaQueryWrapper<BloodInStorgeEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Strings.isNotBlank(bloodId), BloodInStorgeEntity::getBloodId, bloodId);
        BloodInStorgeEntity bloodInStorgeEntity = bloodInStorgeDao.selectOne(queryWrapper);

        if(bloodInStorgeEntity == null){
            throw new MyException(InstorageException.NO_BLOODID_STORAGE);
        }

        if (!BloodStateEnum.IN_STORAGE_TEST.value().equals(bloodInStorgeEntity.getBloodState()) && !BloodStateEnum.IN_STOCK.value().equals(bloodInStorgeEntity.getBloodState())){
            throw new MyException(InstorageException.NO_NEED_TEST);
        }
        return bloodInStorgeEntity;
    }

    @Override
    public int cascadeDelete(BloodDeleteReturnVo vo) {
        List<String> bloodIds = vo.getBloodIds();
        String applyId = vo.getApplyId();
        String applyName = vo.getApplyName();

        LambdaQueryWrapper<BloodInStorgeEntity> storgeQuery = new LambdaQueryWrapper<>();
        storgeQuery.in(BloodInStorgeEntity::getBloodId, bloodIds);
        List<BloodInStorgeEntity> storgeList = this.list(storgeQuery);


        String returnPrefix = ConstantData.BLOOD_RETURN_NO_WORK_ID;
        String dateStr = new java.text.SimpleDateFormat("yyyyMMdd").format(new java.util.Date());
        QueryWrapper<BloodReturnEntity> returnWrapper = new QueryWrapper<>();
        returnWrapper.likeRight("blood_return_id", returnPrefix + dateStr);
        returnWrapper.orderByDesc("blood_return_id");
        returnWrapper.last("limit 1");
        BloodReturnEntity maxReturnEntity = bloodReturnDao.selectOne(returnWrapper);

        int nextReturnSeq = 1;
        if (maxReturnEntity != null && maxReturnEntity.getBloodReturnId() != null) {
            String maxNo = maxReturnEntity.getBloodReturnId();
            if (maxNo.length() >= (returnPrefix.length() + 8 + 4)) {
                String seqStr = maxNo.substring(returnPrefix.length() + 8, returnPrefix.length() + 8 + 4);
                nextReturnSeq = Integer.parseInt(seqStr) + 1;
            }
        }

        // 3. 构造并插入退血记录（去重）
        for (BloodInStorgeEntity storge : storgeList) {
            // 判断该 bloodId 是否已存在退血记录
            LambdaQueryWrapper<BloodReturnEntity> existQuery = new LambdaQueryWrapper<>();
            existQuery.eq(BloodReturnEntity::getBloodId, storge.getBloodId());
            existQuery.eq(BloodReturnEntity::getIsDeleted, 0); // 只查未删除的
            Integer count = bloodReturnDao.selectCount(existQuery);
            if (count != null && count > 0) {
                continue; // 已有退血记录，跳过
            }

            BloodReturnEntity returnEntity = new BloodReturnEntity();
            BeanUtils.copyProperties(storge, returnEntity);

            // 生成唯一退血单号
            String returnSeqStr = String.format("%04d", nextReturnSeq++);
            String bloodReturnId = returnPrefix + dateStr + returnSeqStr;
            returnEntity.setBloodReturnId(bloodReturnId);

            // 设置退血人
            returnEntity.setApplyId(applyId);
            returnEntity.setApplyName(applyName);

            returnEntity.setReason(BloodReturnReasonEnum.DELETE_BLOOD_DATA.code());
            returnEntity.setReview(BloodReturnVerifyStateEnum.PASS.code());



            bloodReturnDao.insert(returnEntity);
        }


        int storageDeleted = this.baseMapper.delete(storgeQuery);

        LambdaQueryWrapper<BloodInformationEntity> informationQuery = new LambdaQueryWrapper<>();
        informationQuery.in(BloodInformationEntity::getBloodId, bloodIds);
        int informationDeleted = bloodInformationDao.delete(informationQuery);

        return storageDeleted + informationDeleted;
    }


}
